#include "stdafx.h"
using namespace std;

#define DEBUG
//#define TEST
#define SCREEN_LOG
#include "poklington_test.h"

int main()
{
#ifdef DEBUG
#undef DEBUG
	int a=394,n=3701;
	cout<<uint128::pow_m(a,n-1,n)<<" is 1\n";
	cout<<uint128::pow_m(a,(n-1)/ 2,n)<<" is not 1\n";
	cout<<uint128::pow_m(a,(n-1)/37,n)<<" is not 1\n";
	return 0;
#endif /* DEBUG */
	srand(int(time(NULL)));
#ifdef TEST
	//  tests 
	ostream &str=cout;
	int t=1;
	
	//first test
	const int N_COMP=1;
	const int COMP=27;
	double res_comp[COMP];
	const uint128 R_COMP[COMP]={2,4,16,2,4,10,4,8,18,2,8,16,6,25,24,46,2,10,70,54,4,6,20,42,50,4,6};
	const unsigned __int8 LENGTH_COMP[COMP]={1,1,1,1,4,2,1,1,2,1,1,1,1,3,1,1,1,1,1,3,1,1,1,1,1,1,2};
	const small_number FACTORS_COMP[COMP][4]={{167,0,0,0},{109,0,0,0},{41,0,0,0},
			    			      		      {389,0,0,0},{3,3,3,11},{7,17,0,0},
							                  {383,0,0,0},{223,0,0,0},{5,23,0,0},
											  {1163,0,0,0},{281,0,0,0},{191,0,0,0},
											  {563,0,0,0},{2,2,37,0},{167,0,0,0},
											  {101,0,0,0},{2503,0,0,0},{521,0,0,0},
											  {127,0,0,0},{5,5,7,0},{2459,0,0,0},
											  {1657,0,0,0},{307,0,0,0},{149,0,0,0},
											  {139,0,0,0},{1789,0,0,0},{29,43,0,0}};
	for(int j=0;j<COMP;++j) res_comp[j]=0;
	for(int i=0;i<N_COMP;++i)
	{
		str<<'.';
		for(int j=0;j<COMP;++j) 
			if(poklington::is_prime(FACTORS_COMP[j],LENGTH_COMP[j],R_COMP[j],t)) ++res_comp[j];
	}
	str<<"\n always composite:\n";for(int j=0;j<COMP;++j) str<<(res_comp[j]/=N_COMP)<<'\t';
	str<<endl;

	//second test
	const int N_PRIME=100;
	const int PRIME=17;
	double res_prime[PRIME];
	const uint128 R_PRIME[PRIME]=             {3,4,4,8,8,4,2,16,2,20,8,20,12,64,72,4,36};
	const unsigned __int8 LENGTH_PRIME[PRIME]={2,1,2,3,1,1,1,2,2,1,2,1,1,2,2,1,2};
	const small_number FACTORS_PRIME[PRIME][3]={{2,2,0},{7,0,0},{3,5,0},
	                                            {3,2,2},{13,0,0},{43,0,0},
											    {89,0,0},{2,11,0},{11,19,0},
	                                            {23,0,0},{7,11,0},{41,0,0}, {89,0,0},
	                                            {3,31,0}, {5,17,0},{1549,0,0},{3,59,0}};
	for(int j=0;j<PRIME;++j) res_prime[j]=0;
	for(int i=0;i<N_PRIME;++i)
	{
		str<<'.';
		for(int j=0;j<PRIME;++j) 
			if(!poklington::is_prime(FACTORS_PRIME[j],LENGTH_PRIME[j],R_PRIME[j],t)) ++res_prime[j];
	}
	str<<"\n frequency of error for prime numbers:\n";for(int j=0;j<PRIME;++j) str<<(res_prime[j]/=N_PRIME)<<'\n';
	str<<endl;
	//  end of tests  
	return 0;
#endif /* TEST */
	const unsigned int N=10;

	ofstream outfile("report.txt");
	ostream &str=
#ifdef SCREEN_LOG
		outfile;
#else /* SCREEN_LOG */
		cout;
#endif /* SCREEN_LOG */  
	const unsigned int WIDTH=86;
	str<<setw(WIDTH)<<setfill('-')<<'\n';
	str<<"| # |                prime number                | primality test |  prime attempts |\n";
	str<<setw(WIDTH)<<setfill('-')<<'\n'<<setfill(' ');
	
	const unsigned int SMALL=500;
	poklington p(SMALL);
	for(int i=0;i<N;++i)
	{
#ifdef SCREEN_LOG
		cout<<"Finding "<<i+1<<" number\n";
#endif /* SCREEN_LOG */
		uint128 prime = p.get_prime(sizeof(uint128)*8);
#ifdef SCREEN_LOG
		cout<<i+1<<"-th prime number has found: "<<prime<<" !\n\n";
#endif /* SCREEN_LOG */	
		str<<'|'<<setw(3)<<i+1
			<<"| "<<prime
			<<" |"<<setw(16)<<(probably_prime(prime)?'+':'-')
			<<"| "<<setw(16)<<p.prime_attempts<<"|\n";
	}
	str<<setw(WIDTH)<<setfill('-')<<'\n';
	outfile.close();
	return 0;
}